//函数调用必须带上形参名字
func foo(name:String){
    print(name)
    
}
foo(name:"testName")
print()

//参数为可选类型
func foo1(name:String?){
    if let name=name {
        print(name)
    }
}
foo1(name:"testName2")
print()

//带返回类型的
func foo2(name:String) -> String{
    return "name is \(name)"
}
print(foo2(name:"testName2"))
print()


//元组返回类型
func foo3(array:[Int]) -> (min:Int, max:Int) {
    var currentMin = array[0]
    var currentMax = array[0]
    for value in array {
        if value < currentMin {
            currentMin = value
        }else if value > currentMax {
            currentMax = value
        }
    }
    return (currentMin, currentMax)
}

let bounds = foo3(array:[2,5,10,18,7])
print("min is \(bounds.min), max is \(bounds.max)")

//可选类型的元组返回
func foo4(array:[Int]) -> (min:Int, max:Int)?{
    if array.isEmpty { return nil }
    var currentMin = array[0]
    var currentMax = array[0]
    for value in array {
        if value < currentMin {
            currentMin = value
        }else if value > currentMax {
            currentMax = value
        }
    }

    return (currentMin, currentMax)
}
let bounds1 = foo4(array:[])
if let bounds = bounds1 {
    print(bounds)
}
print()

//外部参数名,定义了外部参数名，调用函数时必须要用外部参数名
func foo5(firstArg a:Int, secondArg b:Int) -> Int {
    return a+b
}
print("sum is \(foo5(firstArg:4, secondArg:5))")
print()

//可变参数
func foo6<T>(members:T...){
    for item in members {
        print(item)
    }
}
foo6(members:1,2,3,4)
print()

//常量，变量，I/O 参数，函数里面一般都是值传递，而且都是常量的，不能做任何修改的，如果需要改变参数的值，就需要inout
func foo7(_ a: inout Int, _ b: inout Int){
    let temp = a;
    a = b
    b = temp
}
var x=1
var y=9
foo7(&x,&y)
print("x=\(x), y=\(y)")

func foo8(_ array:inout [Int]){
    array.remove(at:0)
}
var intArr4:[Int] = [1,2,3,4]
foo8(&intArr4)
print(intArr4)
print()


//函数类型
func sum(a:Int, b:Int) -> Int {
    return a+b
}

var addition: (Int,Int)->Int = sum
print("sum is \(addition(1,2))")


//回调函数式编程1
func foo9(a:Int, b:Int, callback:(Int,Int) -> Int) -> Int {
    return callback(a,b)
}
var sum1 = foo9(a:10, b:20, callback:{(arg1:Int, arg2:Int) -> Int in
    return arg1+arg2
})
print("sum1 is \(sum1)")

var sum2 = foo9(a:10, b:22){(arg1, arg2) in
    return arg1 + arg2
}
print("sum2 is \(sum2)")

var sum3 = foo9(a:52, b:22){
    return $0 + $1
}
print("sum3 is \(sum3)")

func foo10(callback:()->()){
    callback()
}

foo10{
    print("this is a no args func")
}

func funcBuild(f: @escaping (Int) -> Int, g: @escaping (Int) -> Int)
    -> (Int) -> Int
{
    return { f(g($0)) }
}

let f1 = funcBuild(f: {$0 + 2}, g: {$0 + 3})
print(f1(0)) // 结果为5
let f2 = funcBuild(f: {$0 * 2}, g: {$0 * 5})
print(f2(1)) // 结果为10

typealias intFunction = (Int)->Int
func foo11(f: @escaping intFunction, g: @escaping intFunction)->intFunction {
    return { f(g($0)) }
}
print("\(foo11(f:{ $0+2 }, g:{ $0+3 })(0))")






